负载均衡集群(即LB集群,是load balance集群的简写),简单来说就是让多台服务器均衡地去承载压力。实现负载均衡集群的开源软件有LVS、keepalived、haproxy、Nginx等,当然也有优秀的商业负载均衡设备,比如F5、NetScaler等。商业的负载均衡解决方案稳定性没的说,但是成本非常昂贵,在这篇学习笔记里,以开源产品为主。
LVS、Nginx和haproxy,三者中,LVS稳定性最好,可配置型最少;Nginx针对域名、目录结构进行正则匹配是最强的,同时其对网络依赖比较小,不过性能上和LVS和haproxy相比稍差一点点;haproxy支持虚拟主机,尤其在session保持方面做的最好,其有三种算法可以实现session共享:ip识别(source)、cookie识别、session识别;除此之外在对MySQL做HA方案时也会经常用到该软件。
1. LVS
1.1. LVS介绍
LVS(Linux Virtual Server)是由国内大牛章文嵩开发的,这款软件的流行度不亚于Apache的httpd,它是一款四层的负载均衡软件,是针对TCP/IP做的转发和路由,所以稳定性和效率相当高。不过LVS最新的版本是基于Linux2.6内核的,这意味着它已经有很多年没有更新了。虽然目前越来越多的企业选择使用Nginx实现负载均衡,但LVS依然被诸多企业应用在核心的架构当中。
LVS的架构如下图所示:
LVS架构从逻辑上可分为调度层(Director)、Server集群层(Real Server)和共享存储。
在该架构中有一个核心的角色叫做调度器(Load Blancer),用来分发用户的请求,还有诸多的真实服务器(Real Server),也就是处理用户请求的服务器。
如果不同的机器,可能用户请求到的数据不一样,为了避免这样的情况发生,所有用到了共享存储,这样保证所有用户请求的数据是一样的。
1.2. LVS的三种模式
LVS根据实现方式的不同,主要分为三种类型:NAT模式、IP Tunnel(IP隧道)模式、DR模式。
1. NAT模式
NAT模式和iptables的nat表是一个意思。这种模式的实现原理很简单,调度器会把用户的请求通过预设的iptables规则转发给后端的真实服务器。其中调度器有两个IP,一个是公网IP,一个是内网IP,而真实服务器只有内网IP。用户访问的时候请求的是调度器的公网IP,它会把用户的请求转发到真是服务器的内网IP上。这种模式的好处是节省公网IP,但是调度器会成为一个瓶颈。
NAT模式架构如下图所示:
2. IP Tunnel模式
IP隧道是将一个IP报文封装在另一个IP报文的技术,这可以使目标为一个IP地址的数据报文能被封装和转发到另一个IP地址。像大家所熟知的VPN技术其实就是IP隧道。在LVS的IP Tunnel架构中,后端服务器有一组而非一个,所以不就可能静态地建立一一对应的隧道,而是动态地选择一台服务器,将请求报文封装和转发给选出来的服务器。这样,我们可以利用IP隧道的原理,将一组服务器上的网络服务组成在一个IP地址上的虚拟网络服务。
IP Tunnel模式架构如下图所示:
调度器(Load Blancer)将请求报文封装在另一个IP报文中,再将封装后的IP报文转发给真是服务器。真实服务器接收到报文后,先将报文解封获得原来目标地址为VIP的报文,服务器发现VIP地址被配置在本地的IP隧道设备上,所以就处理这个请求,然后根据路由表将响应报文直接返回给客户。这种模式下,需要给调度器和所有的真实服务器全部分配公网IP,所以比较浪费公网IP。
3. DR模式
和IP Tunnel模式方法相同,用户的请求被调度器动态地分配到真实服务器上,真实服务器响应请求把结果直接返回给用户。不过这种模式下不会封装IP,而是将数据帧的MAC地址改为真实服务器的MAC地址。
DR模式架构如下图所示
4. 三种模式的比较
LVS的官网给出了三种模式的比较,如下表所示:
_ | VS/NAT | VS/TUN | VS/DR |
---|---|---|---|
server | any | Tunneling | Non-arp device |
server network | private | LAN/WAN | LAN |
server number | low(10-20) | High(100) | High(100) |
server gateway | load balancer | own router | own router |
以上三种方法所支持最大服务器数的估计值是假设调度器使用100MB网卡,调度器的硬件配置与后端服务器的硬件配置相同,而且是针对一般Web服务的。使用更高的硬件配置(如千兆网卡和更快的处理器)作为调度器,调度器所能调度的服务器数量会相应增加。当应用不同时,服务器的数目也会相应地改变。所以,以上数据估计主要是为三种方法的伸缩性进行了量化比较。
根据上表中的比较也可以看出,NAT模式适合小型的集群,机器数量不多,它的优势是节省公网IP。TUN和DR相差不大,都能支撑较大规模的集群,但缺点就是浪费公网IP。
1.3. LVS的调度算法
调度器把客户端发来的请求均衡地分发给后端的真实服务器,这是依靠预先设定好的调度算法实现的,在LVS中支持的调度算法主要有以下8种。
1. 轮询调度(Round-Robin)rr
是非常简单的一种调度算法,就是按顺序把请求一依次发送给后端的服务器,它不管后端服务器的处理速度和响应时间怎样。当后端服务器性能不一致时,这种调度算法就不合适了。
2. 带权重的轮询调度(Weighted Round-Robin)wrr
比第一种算法多了一个权重的设置,权重越高的服务器被分配到的请求就越多,这样后端服务器性能不一致时,就可以给配置低的服务器较小的权重。
3. 最小连接调度(Least-Connection)lc
这种算法会根据各真实服务器上的连接数来决定把新的请求分配给谁,连接数少说明服务器是空闲的,这样把新的请求分配到空闲服务器上才更加合理。
4. 带权重的最小连接调度(Weighted Least-Connection)wlc
在最小连接调度的基础上再增加一个权重设置,这样就可以人为的去控制哪些服务器上多分配请求,哪些少分配请求。
5. 基于局部性的最少连接调度(Locality-Based Least Connection)lblc
这种算法检测LBLC,是针对请求报文的目标IP地址的负载均衡调度,目前主要用于Cache集群系统,因为在Cache集群中客户请求报文的目标IP地址是变化的。算法的设计目标是在服务器的负载均衡的情况下,将相同目标IP地址的请求调度到同一台服务器,来提高各服务器的访问局部性和主存Cache命中率。
6. 带复制的基于局部性最少连接调度(Locality-Based Least Connection with Replication)
该算法简称LBLCR,也是针对目标IP地址的负载均衡,它与LBLC算法的不同之处是:它要维护从一个目标IP地址到一组服务器的映射,而LBLC算法是维护从一个目标IP地址到一台服务器的映射。LBLCR算法先根据请求的目标IP地址找出该目标IP地址对应的服务器组,按“最小连接”原则从该服务器组中选出一台服务器,若服务器没有超载,则将请求发送到该服务器;若服务器超载,则按“最小连接”原则从整个集群中选出一台服务器,将该服务器加入到服务器组中,将请求发送到该服务器。同时,当该服务器组有一段时间没有被修改,将最忙的服务器从服务器组中删除,以降低复制的程度。
7. 目标地址散列调度(Destination Hashing)dh
该算法也是针对目标IP地址的负载均衡的,但它是一种静态映射算法,通过一个散列(hash)函数将一个目标IP地址映射到一台服务器。目标地址散列调度算法先根据请求的目标IP地址,作为散列键(hash key)从静态分配的散列表找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。
8. 源地址散列调度(source Hashing)sh
该算法正好与目标地址散列调度算法相反,它根据请求的源IP地址,作为散列键从静态分配的散列表中找出对应的服务器,若该服务器是可用的且未超载,将请求发送到该服务器,否则返回空。它的算法流程与目标地址散列调度算法的基本类似,只不过将请求的目标IP地址换成请求的源IP地址。
对于以上8种调度算法,前面4种用得最多,也最容易理解,它们基本上能满足绝大多数的应用场景。关于这部分,最好仔细看看,可能面试的时候会被闻到。
下面,介绍NAT模式和DR模式的LVS配置方法。
1.4. NAT模式LVS搭建
NAT模式下,调度器需要有两个IP,一个公网IP和一个内网IP,真实服务器只需要内网IP。此架构需要准备三台机器。
三台机器的IP分配如下:
- 调度器dir:192.168.188.128(内网)、192.168.147.144(公网IP,Vmware仅主机网络模式)
- 真实服务器rs1:192.168.188.129(内网IP)
- 真实服务器rs2:192.168.188.127(内网IP)
其中,调度器上有两块网卡,作为内网的这块网卡使用的是NAT的网络,而作为“公网”的网卡使用的是仅主机网络。注意,所谓的公网仅仅是模拟的,并不是真正意义上的公网。
在配置LVS之前,需要做一些准备工作。首先,真实服务器rs1(192.168.188.129)和rs2(192.168.188.127)上需要把内网的网关设置为dir的内网IP(192.168.188.128),否则实验无法成功。然后,我们把三台服务器上的iptables规则清空并保存。
在dir上安装ipvsadm,这是实现LVS的核心工具:
继续在dir上编写一个脚本:vim /usr/local/sbin/lvs_nat.sh
,脚本内容如下:
其中:
iptables
的-C选项可以清空规则,防止之前的规则有影响-A
增加Virtual Server-t
w欸TCP-s
选项指定调度算法,wlc为带权重的最小连接算法-p
指定超时时间(这里的300为300秒,它表示300秒内相同用户的请求会一直被调度到同一台rs上。在测试时,建议不要加这个选项,否则后面验证时会比较麻烦)-a
增加rs-r
指定rs的IP-m
表示LVS的模式为NAT(masquerad),如果是-g
表示LVS模式为DR,-i
表示LVS模式为IP Tunnel-w
指定权重(1-100)
编辑完脚本后,直接执行就完成了LVS的配置了:
下面就该测试LVS的效果了,如果dir上有开启Ngixn,需要把它关闭,否则会影响实验效果:killall nginx
为了更容易区分,需要分别给129和127设置一个默认主页,在这个实验环境中,127为128机器的克隆,所以127上的Nginx为编译的Nginx,129上为yum安装的:
现在dir分别访问两个rs,结果如下:
这样就区分开了rs1和rs2,然后直接在dir上访问dir的外网IP(192。168.147.144),结果如下:
连续访问多次,一直请求到rs2上,这是因为在前面的脚本中有设置-p
参数,理论上在300秒内会一直请求到rs2上。
重新编辑脚本把-p参数删除了,然后再次测试,结果如下:
这次就做到了均衡访问。
1.5. DR模式LVS搭建
DR模式同样需要三太虚拟机,三台机器只需要有“公网”IP,但这种模式下又多了一个VIP,先列一下对应的机器和IP:
- 调度器dir:192.168.188.128
- 真实服务器rs1:192.168.188.129
- 真实服务器rs2:192.168.188.127
- VIP:192.168.188.110
这次,把NAT模式下的内网IP变成了“公网”IP,所谓VIP和在高可用集群里面的VIP是一个概念。只要记得在实验的机器,两台rs上的网关改成原始网关,不能继续设置为dir的IP地址了。和NAT模式类似,DR模式也需要在dir上编写一个Shell脚本:vim /usr/local/sbin/lvs_dr.sh
,脚本内容如下:
两台rs上也需要编写脚本(内容一样):vim /usr/local/sbin/lvs_dr_rs.sh
分别在三台机器上执行各自的脚本:
执行完三个脚本后,就可以测试了。但这次不能在dir上用curl命令测试了,因为VIP在三台机器上都有设置,直接去curl访问VIP的话不可能成功。所以只能用浏览器来测试结果。
测试结果省略。
2. keepalived+LVS
LVS架构中,不管是NAT模式还是DR模式,当后端的RS宕机时,调度器依然会把请求转发到宕掉的RS上,这样的结果并不是我们想要的。其实,keepalived就可以解决该问题,它不仅有高可用的功能,还有负载均衡的功能。在调度器上只要安装了keepalived,就不用去编写LVS的相关脚本了,就是说keepalived已经嵌入了LVS的功能。keepalived的作用除了可以检测RS状态外,还可以检测备用director的状态。
完整的keepalived+LVS架构需要有两台调度器实现高可用,提供调度服务的只需要一台,另外一台作为备用。
2.1. 环境说明
下面是做实验的各机器的角色和IP:
- 主keepalived(调度器):192.168.31.166(外网)
- 从keepalived(调度器):192.168.31.167(外网)
- 真实服务器rs1:192.168.31.100
- 真实服务器rs2:192.168.31.101
- VIP:192.168.31.110
2.2. 配置过程
两台director上都要安装keepalived(也可以把ipvsadm安装上):
director上安装好keepalived后,编辑其配置文件。
主director:vim /etc/keepalived/keepalived.conf
,加入或更改如下配置:
从director的配置文件和主的一致,只需要修改如下内容:
修改完后的完整配置如下:
配置完keepalived后,先做一些操作:
因为上面在keepalived的配置文件中定义的LVS的模式为DR模式,所以还需要在两台RS上执行lvs_dr_rs脚本,这个脚本也就是在上一节中设置的脚本,其内容如下:
然后rs1和rs2上都执行这个脚本:
最后,两个director上启动keepalived服务(先主后从,但要确保真实服务器上的主服务比如Nginx要启动才能得到正确的结果):
然后就可以进行测试了。在这里,测试省略。
3. Nginx的负载均衡集群
Nginx也有负载均衡的功能,实际上它和Nginx的代理是同一个功能,只不过是把之前代理一台机器改为代理多台机器而已。
Nginx的负载均衡和LVS相比,Nginx属于更高级的应用层,不牵扯到IP和内核的改动,它只是单纯地把用户的请求转发到后面的真实服务器上面。这也意味着,后端的RS不需要配置公网IP。
3.1. 环境说明
- Nginx分发器:192.168.31.166(公网IP)、192.168.21.166(内网IP)
- RS1:192.168.21.100(只有内网IP)
- RS2:192.168.21.101(只有内网IP)
3.2. 配置过程
在Nginx分发器上编辑配置文件:vim /usr/local/nginx/conf/vhosts/lb.conf
,加入如下内容:
说明:
upstream
用来定义后端的RS,可以只写一个,也可以写多个。ip_hash
是Nginx的一种调度算法,加上这一行后会达到这样的效果,即一个用户的请求会适中被分发到固定的一个RS上。这样做的好处是,可以避免同一个用户的请求分发到不同的机器上而导致session丢失的情况。- upstream里面,RS后面的ip后面还可以加权重,比如
server 192.168.31.100 weight=100;
- 还有一点需要注意,upstream后面的test是自定义的一个名字,可以随便写,唯一的要求就是要和proxy_pass后面保持一致。
然后,启动Nginx分发器进行测试即可。在这里,测试省略。